#include <stdlib.h>
/*
*   Source : http://www.siteduzero.com/tutoriel-3-36245-les-listes-chainees.html
*/
#include "list.h"

llist ajouterEnTete(llist liste, int valeur)
{

    element* nouvelElement = malloc(sizeof(element));

    nouvelElement->val = valeur;
 

    nouvelElement->nxt = liste;
 

    return nouvelElement;
}

llist ajouterEnFin(llist liste, int valeur)
{
    element* nouvelElement = malloc(sizeof(element));
    nouvelElement->val = valeur;
    nouvelElement->nxt = NULL;
    if(liste == NULL)
    {
        return nouvelElement;
    }
    else
    {
        element* temp=liste;
        while(temp->nxt != NULL)
        {
            temp = temp->nxt;
        }
        temp->nxt = nouvelElement;
        return liste;
    }
}

void afficherListe(llist liste)
{
    element *tmp = liste;
    
    while(tmp != NULL)
    {
        /* On affiche */
        printf("%d ", tmp->val);
        /* On avance d'une case */
        tmp = tmp->nxt;
    }
}

int estVide(llist liste)
{
    if(liste == NULL)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

llist supprimerElementEnTete(llist liste)
{
    if(liste != NULL)
    {
        /* Si la liste est non vide, on se prÃ©pare Ã  renvoyer l'adresse de
        l'Ã©lÃ©ment en 2Ã¨me position */
        element* aRenvoyer = liste->nxt;
        /* On libÃ¨re le premier Ã©lÃ©ment */
        free(liste);
        /* On retourne le nouveau dÃ©but de la liste */
        return aRenvoyer;
    }
    else
    {
        return NULL;
    }
}

llist supprimerElementEnFin(llist liste)
{
    /* Si la liste est vide, on retourne NULL */
    if(liste == NULL)
        return NULL;
 
    /* Si la liste contient un seul Ã©lÃ©ment */
    if(liste->nxt == NULL)
    {
        /* On le libÃ¨re et on retourne NULL (la liste est maintenant vide) */
        free(liste);
        return NULL;
    }
 
    /* Si la liste contient au moins deux Ã©lÃ©ments */
    element* tmp = liste;
    element* ptmp = liste;
    /* Tant qu'on n'est pas au dernier Ã©lÃ©ment */
    while(tmp->nxt != NULL)
    {
        /* ptmp stock l'adresse de tmp */
        ptmp = tmp;
        /* On dÃ©place tmp (mais ptmp garde l'ancienne valeur de tmp */
        tmp = tmp->nxt;
    }
    /* A la sortie de la boucle, tmp pointe sur le dernier Ã©lÃ©ment, et ptmp sur
    l'avant-dernier. On indique que l'avant-dernier devient la fin de la liste
    et on supprime le dernier Ã©lÃ©ment */
    ptmp->nxt = NULL;
    free(tmp);
    return liste;
}

llist rechercherElement(llist liste, int valeur)
{
    element *tmp=liste;
    /* Tant que l'on n'est pas au bout de la liste */
    while(tmp != NULL)
    {
        if(tmp->val == valeur)
        {
            /* Si l'Ã©lÃ©ment a la valeur recherchÃ©e, on renvoie son adresse */
            return tmp;
        }
        tmp = tmp->nxt;
    }
    return NULL;
}

int nombreOccurences(llist liste, int valeur)
{
    int i = 0;
 
    /* Si la liste est vide, on renvoie 0 */
    if(liste == NULL)
        return 0;
 
    /* Sinon, tant qu'il y a encore un Ã©lÃ©ment ayant la val = valeur */
    while((liste = rechercherElement(liste, valeur)) != NULL)
    {
        /* On incrÃ©mente */
        liste = liste->nxt;
        i++;
    }
    /* Et on retourne le nombre d'occurrences */
    return i;
}

llist element_i(llist liste, int indice)
{
    int i;
    /* On se dÃ©place de i cases, tant que c'est possible */
    for(i=0; i<indice && liste != NULL; i++)
    {
        liste = liste->nxt;
    }
 
    /* Si l'Ã©lÃ©ment est NULL, c'est que la liste contient moins de i Ã©lÃ©ments */
    if(liste == NULL)
    {
        return NULL;
    }
    else
    {
        /* Sinon on renvoie l'adresse de l'Ã©lÃ©ment i */
        return liste;
    }
}

int nombreElements(llist liste)
{
    /* Si la liste est vide, il y a 0 Ã©lÃ©ment */
    if(liste == NULL)
        return 0;
 
    /* Sinon, il y a un Ã©lÃ©ment (celui que l'on est en train de traiter)
    plus le nombre d'Ã©lÃ©ments contenus dans le reste de la liste */
    return nombreElements(liste->nxt)+1;
}

llist supprimerElement(llist liste, int valeur)
{
    /* Liste vide, il n'y a plus rien Ã  supprimer */
    if(liste == NULL)
        return NULL;
 
    /* Si l'Ã©lÃ©ment en cours de traitement doit Ãªtre supprimÃ© */
    if(liste->val == valeur)
    {
        /* On le supprime en prenant soin de mÃ©moriser 
        l'adresse de l'Ã©lÃ©ment suivant */
        element* tmp = liste->nxt;
        free(liste);
        /* L'Ã©lÃ©ment ayant Ã©tÃ© supprimÃ©, la liste commencera Ã  l'Ã©lÃ©ment suivant
        pointant sur une liste qui ne contient plus aucun Ã©lÃ©ment ayant la valeur recherchÃ©e */
        tmp = supprimerElement(tmp, valeur);
        return tmp;
    }
    else
    {
        /* Si l'Ã©lement en cours de traitement ne doit pas Ãªtre supprimÃ©,
        alors la liste finale commencera par cet Ã©lÃ©ment et suivra une liste ne contenant
        plus d'Ã©lÃ©ment ayant la valeur recherchÃ©e */
        liste->nxt = supprimerElement(liste->nxt, valeur);
        return liste;
    }
}

/* AJOUTS */

llist arrayToList(int* tableau)
{
  llist resultat = NULL;
  int i = 0;
  for(i ; i < (sizeof(tableau)/sizeof(int)) ; i++)
  {
    ajouterEnFin(resultat, tableau[i]);
  }
  return resultat;
}

int* listToArray(llist liste)
{
  int* resultat= malloc(sizeof(int)*nombreElements(liste));
  llist tmp = liste;
  int i = 0;
  while(tmp != NULL)
  {
    resultat[i]= tmp->val;
    tmp = tmp->nxt;
    i++;
  }
  return resultat;
}
